package com.aeoj.clientmanagement.service.impl;

import com.aeoj.clientmanagement.domain.judge.JudgeResult;
import com.aeoj.clientmanagement.domain.problem.Problem;
import com.aeoj.clientmanagement.domain.problemrecord.ProblemRecord;
import com.aeoj.clientmanagement.enums.problem.ProblemRrecordStatusEnum;
import com.aeoj.clientmanagement.enums.ResponseCodeEnum;
import com.aeoj.clientmanagement.exception.BusinessException;
import com.aeoj.clientmanagement.factory.CodeSandBoxFactory;
import com.aeoj.clientmanagement.proxy.CodeSandBoxProxy;
import com.aeoj.clientmanagement.domain.codesandbox.CodeSandBoxRequest;
import com.aeoj.clientmanagement.domain.codesandbox.CodeSandBoxResponse;
import com.aeoj.clientmanagement.manager.JudgeManager;
import com.aeoj.clientmanagement.service.CodeSandBoxService;
import com.aeoj.clientmanagement.service.JudgeService;
import com.aeoj.clientmanagement.service.ProblemService;
import com.aeoj.clientmanagement.strategy.JudgeStrategyContext;
import com.aeoj.clientmanagement.service.ProblemRecordService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * author: ZSM
 * time: 2025-03-01 20:08
 */
@Service
public class JudgeServiceImpl implements JudgeService {
    @Value("${judge.codesandbox.type:native}")
    private String codesandboxType;
    @Resource
    private ProblemRecordService problemRecordService;
    @Resource
    private ProblemService problemService;
    @Resource
    private JudgeManager judgeManager;

    @Override
    public ProblemRecord doJudge(Long problemRecordId) {
        // 获取提交记录信息
        ProblemRecord problemRecord = problemRecordService.getById(problemRecordId);
        if (problemRecord == null) {
            throw new BusinessException(ResponseCodeEnum.BUSINESS_ERROR, "提交记录不存在");
        }

        // 判断当前是否是等待中状态
        String status = problemRecord.getStatus();
        if (!ProblemRrecordStatusEnum.getByCode(status).equals(ProblemRrecordStatusEnum.PENDING)) {
            throw new BusinessException(ResponseCodeEnum.BUSINESS_ERROR, "重复判题操作");
        }

        Long problemId = problemRecord.getProblemId();
        Problem problem = problemService.getById(problemId);
        if (problem == null) {
            throw new BusinessException(ResponseCodeEnum.BUSINESS_ERROR, "题目不存在");
        }
        problem.setSubmissionCount(problem.getSubmissionCount() + 1);
        problemService.updateById(problem);

        // 将状态设置为判题中
        problemRecord.setStatus(ProblemRrecordStatusEnum.JUDGING.getCode());
        problemRecordService.updateById(problemRecord);

        // 通过代码沙箱代理来调用代码沙箱
        CodeSandBoxService codeSandBoxService = CodeSandBoxFactory.createCodeSandBox(codesandboxType);
        CodeSandBoxProxy codeSandBoxProxy = new CodeSandBoxProxy(codeSandBoxService);

        List<String> inputCasesList = null;
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            inputCasesList = objectMapper.readValue(problem.getInputCases(), new TypeReference<List<String>>() {
            });
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        CodeSandBoxRequest codeSandBoxRequest = CodeSandBoxRequest.builder()
                .language(problemRecord.getLanguage())
                .code(problemRecord.getCode())
                .inputs(inputCasesList)
                .build();

        // 获取到判题结果信息
        CodeSandBoxResponse codeSandBoxResponse = codeSandBoxProxy.execute(codeSandBoxRequest);
        if (codeSandBoxResponse.getExitCode() != 0) {
            problemRecord.setStatus(codeSandBoxResponse.getStatus());
            problemRecord.setMessage(codeSandBoxResponse.getMessage());
            problemRecordService.updateById(problemRecord);
            return problemRecord;
        }
        List<String> outputsByCodeBox = codeSandBoxResponse.getOutputs();

        JudgeStrategyContext judgeStrategyContext = new JudgeStrategyContext();
        judgeStrategyContext.setInputs(inputCasesList);
        judgeStrategyContext.setOutputs(outputsByCodeBox);
        judgeStrategyContext.setProblem(problem);
        judgeStrategyContext.setProblemRecord(problemRecord);
        judgeStrategyContext.setTime(codeSandBoxResponse.getTime());
        judgeStrategyContext.setMemory(codeSandBoxResponse.getMemory());

        JudgeResult judgeResult = judgeManager.doJudge(judgeStrategyContext);
        if (judgeResult.getStatus().equals(ProblemRrecordStatusEnum.ACCEPTED.getCode())) {
            problem.setAcceptedCount(problem.getAcceptedCount() + 1);
            problemService.updateById(problem);
        }

        // 更新提交记录
        problemRecord.setStatus(judgeResult.getStatus());
        problemRecord.setMemory(judgeStrategyContext.getMemory().toString());
        problemRecord.setTime(judgeStrategyContext.getTime().toString());
        problemRecord.setRemark(judgeResult.getMessage());
        problemRecord.setInput(judgeResult.getInput());
        problemRecord.setOutput(judgeResult.getOutput());
        problemRecordService.updateById(problemRecord);

        return problemRecordService.getById(problemRecordId);
    }
}
